home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / What's New? / Development Kits / Apple Game Sprockets DR1 / Examples / DroneZone / DZSliderCDEF.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-24  |  17.2 KB  |  752 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    File:        DZDZSliderCDEF.c
  3.  *    Author:        Dan Venolia
  4.  *
  5.  *    Copyright © 1996 Apple Computer, Inc.
  6.  */
  7.  
  8. #include <Controls.h>
  9. #include <Events.h>
  10. #include <Fonts.h>
  11. #include <Memory.h>
  12. #include <QDOffscreen.h>
  13. #include <Quickdraw.h>
  14.  
  15.  
  16. enum {
  17.     kThumbLeft        = 13,                // Amount of thumb hanging to the left
  18.     kThumbRight        = kThumbLeft+1        // One more because of drop shadow
  19. };
  20.  
  21.  
  22. typedef struct PrivateData {
  23.     GWorldPtr        offscreen;
  24.     short            offset;
  25.     short            origValue;
  26. } PrivateData;
  27.  
  28.  
  29. typedef struct DragRecord {
  30.     Rect            limitRect;
  31.     Rect            slopRect;
  32.     short            axis;
  33. } DragRecord;
  34.  
  35.  
  36. pascal long main(
  37.     short            inVariation,
  38.     ControlHandle    inControl,
  39.     short            inMessage,
  40.     long            inData);
  41.  
  42. static void DoInitCntl(
  43.     ControlHandle    inControl,
  44.     short            inVariation);
  45.  
  46. static void DoDispCntl(
  47.     ControlHandle    inControl);
  48.  
  49. static void DoDrawCntl(
  50.     ControlHandle    inControl,
  51.     short            inVariation,
  52.     long            inPartCode);
  53.  
  54. static long DoTestCntl(
  55.     ControlHandle    inControl,
  56.     short            inVariation,
  57.     Point            inPoint);
  58.  
  59. static void DoPosCntl(
  60.     ControlHandle    inControl,
  61.     short            inVariation,
  62.     Point            inDelta);
  63.  
  64. static void DoThumbCntl(
  65.     ControlHandle    inControl,
  66.     short            inVariation,
  67.     DragRecord*        inDragRecord);
  68.  
  69. static void DoDragCntl(
  70.     ControlHandle    inControl,
  71.     short            inVariation);
  72.  
  73. static void DoCalcCntlRgn(
  74.     ControlHandle    inControl,
  75.     short            inVariation,
  76.     RgnHandle        ioRegion);
  77.  
  78. static void DoCalcThumbRgn(
  79.     ControlHandle    inControl,
  80.     short            inVariation,
  81.     RgnHandle        ioRegion);
  82.  
  83. static short ValToPos(
  84.     ControlHandle    inControl,
  85.     short            inVariation);
  86.  
  87. static void PosToVal(
  88.     ControlHandle    inControl,
  89.     short            inVariation,
  90.     short            inPosition);
  91.  
  92. static void NumToPStr(
  93.     Str255            outStr,
  94.     long            inValue);
  95.  
  96.  
  97. /* =============================================================================
  98.  *        main (external)
  99.  *
  100.  *    The main entry point.  Dispatches on inMessage.
  101.  * ========================================================================== */
  102. pascal long main(
  103.     short            inVariation,
  104.     ControlHandle    inControl,
  105.     short            inMessage,
  106.     long            inData)
  107. {
  108.     long            result;
  109.     GrafPtr            oldPort;
  110.     
  111.     result = 0;
  112.     
  113.     GetPort(&oldPort);
  114.     SetPort((*inControl)->contrlOwner);
  115.     
  116.     if ((*inControl)->contrlData != NULL || inMessage == initCntl)
  117.     {
  118.         switch (inMessage)
  119.         {
  120.             case drawCntl:
  121.                 DoDrawCntl(inControl, inVariation, inData);
  122.             break;
  123.             
  124.             case testCntl:
  125.                 result = DoTestCntl(inControl, inVariation, * (Point*) &inData);
  126.             break;
  127.             
  128.             case calcCRgns:  // Only on 24-bit systems
  129.                 if (inData < 0)
  130.                 {
  131.                     DoCalcThumbRgn(inControl, inVariation, (RgnHandle) (inData & 0x0FFFFFFF));
  132.                 }
  133.                 else
  134.                 {
  135.                     DoCalcCntlRgn(inControl, inVariation, (RgnHandle) inData);
  136.                 }
  137.             break;
  138.             
  139.             case initCntl:
  140.                 DoInitCntl(inControl, inVariation);
  141.             break;
  142.             
  143.             case dispCntl:
  144.                 DoDispCntl(inControl);
  145.             break;
  146.             
  147.             case posCntl:
  148.                 DoPosCntl(inControl, inVariation,  * (Point*) &inData);
  149.             break;
  150.             
  151.             case thumbCntl:
  152.                 DoThumbCntl(inControl, inVariation, (DragRecord*) inData);
  153.             break;
  154.             
  155.             case dragCntl:
  156.                 DoDragCntl(inControl, inVariation);
  157.                 result = 1;
  158.             break;
  159.             
  160.             case autoTrack:
  161.                 // not needed
  162.             break;
  163.             
  164.             case calcCntlRgn:
  165.                 DoCalcCntlRgn(inControl, inVariation, (RgnHandle) inData);
  166.             break;
  167.             
  168.             case calcThumbRgn:
  169.                 DoCalcThumbRgn(inControl, inVariation, (RgnHandle) inData);
  170.             break;
  171.             
  172.             case drawThumbOutline:
  173.                 // ???
  174.             break;
  175.         }
  176.     }
  177.     
  178.     SetPort(oldPort);
  179.     
  180.     return result;
  181. }
  182.  
  183.  
  184. /* =============================================================================
  185.  *        DoInitCntl (internal)
  186.  *
  187.  *    Initializes the control.  Allocates our private data.
  188.  * ========================================================================== */
  189. void DoInitCntl(
  190.     ControlHandle    inControl,
  191.     short            inVariation)
  192. {
  193.     PrivateData**    privateData;
  194.     
  195.     // Allocate our private data
  196.     (*inControl)->contrlData = NewHandle(sizeof(PrivateData));
  197.     if ((*inControl)->contrlData == NULL || MemError() != noErr)
  198.     {
  199.         DoDispCntl(inControl);
  200.         return;
  201.     }
  202.     
  203.     // Initialize fields
  204.     privateData = (PrivateData**) (*inControl)->contrlData;
  205.     (*privateData)->offscreen = NULL;
  206.     (*privateData)->offset = 0;
  207.     (*privateData)->origValue = 0;
  208.     
  209.     // Allocate the offscreen gworld
  210.     if (NewGWorld(
  211.             &(*privateData)->offscreen,
  212.             32,
  213.             &(*inControl)->contrlRect,
  214.             NULL,
  215.             NULL,
  216.             0) != noErr)
  217.     {
  218.         DoDispCntl(inControl);
  219.         return;
  220.     }
  221. }
  222.  
  223.  
  224. /* =============================================================================
  225.  *        DoDispCntl (internal)
  226.  *
  227.  *    Disposes of the private data.
  228.  * ========================================================================== */
  229. void DoDispCntl(
  230.     ControlHandle    inControl)
  231. {
  232.     PrivateData**    privateData = (PrivateData**) (*inControl)->contrlData;
  233.     
  234.     if (privateData != NULL)
  235.     {
  236.         if ((*privateData)->offscreen != NULL)
  237.         {
  238.             DisposeGWorld((*privateData)->offscreen);
  239.             (*privateData)->offscreen = NULL;
  240.         }
  241.         
  242.         DisposeHandle((Handle) privateData);
  243.         (*inControl)->contrlData = NULL;
  244.     }
  245. }
  246.  
  247.  
  248. /* =============================================================================
  249.  *        DoDrawCntl (internal)
  250.  *
  251.  *    Displays the slider.  It renders it offscreen, then copies it on.  The
  252.  *    inPartCode is ignored.
  253.  * ========================================================================== */
  254. void DoDrawCntl(
  255.     ControlHandle    inControl,
  256.     short            inVariation,
  257.     long            inPartCode)
  258. {
  259.     PrivateData**    privateData = (PrivateData**) (*inControl)->contrlData;
  260.     GWorldPtr        offscreen = (*privateData)->offscreen;
  261.     CGrafPtr        oldGrafPort;
  262.     GDHandle        oldGDevice;
  263.     Point            center;
  264.     Rect            bounds;
  265.     Rect            thumb;
  266.     RGBColor        color;
  267.     RGBColor        backColor;
  268.     RGBColor        foreColor;
  269.     Str255            value;
  270.     Boolean            colorWindow;
  271.     
  272.     if ((*inControl)->contrlVis)
  273.     {
  274.         // Handle changing control size
  275.         if (offscreen->portRect.right - offscreen->portRect.left <
  276.                 (*inControl)->contrlRect.right - (*inControl)->contrlRect.left ||
  277.             offscreen->portRect.bottom - offscreen->portRect.top <
  278.                 (*inControl)->contrlRect.bottom - (*inControl)->contrlRect.top)
  279.         {
  280.             if (UpdateGWorld(
  281.                     &(*privateData)->offscreen,
  282.                     32,
  283.                     &(*inControl)->contrlRect,
  284.                     NULL,
  285.                     NULL,
  286.                     0) != noErr)
  287.             {
  288.                 DoDispCntl(inControl);
  289.                 return;
  290.             }
  291.         }
  292.         
  293.         // Prepare for drawing
  294.         LockPixels(offscreen->portPixMap);
  295.         
  296.         GetGWorld(&oldGrafPort, &oldGDevice);
  297.         SetGWorld(offscreen, NULL);
  298.         
  299.         colorWindow = ((*inControl)->contrlOwner->portBits.rowBytes & 0xC000) != 0;
  300.         
  301.         // Find the thumb center
  302.         bounds = offscreen->portRect;
  303.         center.v = (bounds.top+bounds.bottom+1) >> 1;
  304.         center.h = ValToPos(inControl, inVariation);
  305.         
  306.         // Clear to the same background as the owner window
  307.         if (colorWindow)
  308.         {
  309.             color.red = color.green = color.blue = 0x0000;
  310.             RGBForeColor(&((CGrafPtr) (*inControl)->contrlOwner)->rgbBkColor);
  311.             PaintRect(&offscreen->portRect);
  312.         }
  313.         else
  314.         {
  315.             EraseRect(&offscreen->portRect);
  316.         }
  317.         
  318.         // Draw the slider
  319.         bounds.top    = center.v - 4;
  320.         bounds.bottom = center.v + 4;
  321.         
  322.         if ((*inControl)->contrlHilite != 255)
  323.         {
  324.             color.red = color.green = color.blue = 0xAAAA;
  325.             RGBForeColor(&color);
  326.             PaintRoundRect(&bounds, 8, 8);  // Draw the background
  327.             
  328.             color.red = color.green = color.blue = 0x2222;
  329.         }
  330.         else
  331.         {
  332.             color.red = color.green = color.blue = 0x8888;
  333.         }
  334.         
  335.         RGBForeColor(&color);
  336.         FrameRoundRect(&bounds, 8, 8);  // Draw the outer roundrect
  337.         
  338.         InsetRect(&bounds, 2, 2);
  339.         FrameRoundRect(&bounds, 4, 4);  // Draw the inner roundrect
  340.         
  341.         // Draw the thumb
  342.         if ((*inControl)->contrlHilite != 255)
  343.         {
  344.             // Draw the thumb graphic
  345.             thumb.top    = offscreen->portRect.top;
  346.             thumb.left   = center.h-kThumbLeft;
  347.             thumb.bottom = offscreen->portRect.bottom;
  348.             thumb.right  = center.h+kThumbRight;
  349.             
  350.             color.red = color.green = color.blue = 0xAAAA;
  351.             RGBForeColor(&color);
  352.             
  353.             bounds = thumb;
  354.             thumb.bottom -= 1;
  355.             bounds.left += 2;
  356.             bounds.top = thumb.bottom;
  357.             PaintRect(&bounds);  // Draw the drop shadow horiz part
  358.             
  359.             bounds = thumb;
  360.             thumb.right -= 1;
  361.             bounds.top += 1;
  362.             bounds.left = thumb.right;
  363.             PaintRect(&bounds);  // Draw the drop shadow vert part
  364.             
  365.             color.red = color.green = color.blue = 0x2222;
  366.             RGBForeColor(&color);
  367.             FrameRect(&thumb);  // Draw the thumb outline
  368.             
  369.             InsetRect(&thumb, 1, 1);
  370.             
  371.             color.red = color.green = color.blue = 0xCCCC;
  372.             RGBForeColor(&color);
  373.             PaintRect(&thumb);  // Draw the thumb background
  374.             
  375.             color.red = color.green = color.blue = 0x8888;
  376.             RGBForeColor(&color);
  377.             
  378.             bounds.top    = thumb.bottom-1;
  379.             bounds.left   = thumb.left+1;
  380.             bounds.bottom = thumb.bottom;
  381.             bounds.right  = thumb.right;
  382.             PaintRect(&bounds);  // Draw the dark shadow horiz part
  383.             
  384.             bounds.top    = thumb.top+1;
  385.             bounds.left   = thumb.right-1;
  386.             bounds.bottom = thumb.bottom-1;
  387.             bounds.right  = thumb.right;
  388.             PaintRect(&bounds);  // Draw the dark shadow vert part
  389.             
  390.             color.red = color.green = color.blue = 0xAAAA;
  391.             RGBForeColor(&color);
  392.             
  393.             bounds.top    = thumb.bottom-2;
  394.             bounds.left   = thumb.left+2;
  395.             bounds.bottom = thumb.bottom-1;
  396.             bounds.right  = thumb.right-1;
  397.             PaintRect(&bounds);  // Draw the light shadow horiz part
  398.             
  399.             bounds.top    = thumb.top+2;
  400.             bounds.left   = thumb.right-2;
  401.             bounds.bottom = thumb.bottom-2;
  402.             bounds.right  = thumb.right-1;
  403.             PaintRect(&bounds);  // Draw the light shadow vert part
  404.             
  405.             color.red = color.green = color.blue = 0xEEEE;
  406.             RGBForeColor(&color);
  407.             
  408.             bounds.top    = thumb.top;
  409.             bounds.left   = thumb.left;
  410.             bounds.bottom = thumb.top+2;
  411.             bounds.right  = thumb.left+2;
  412.             PaintRect(&bounds);  // Draw the hilite topleft part
  413.             
  414.             bounds.top    = thumb.top+1;
  415.             bounds.left   = thumb.left+2;
  416.             bounds.bottom = thumb.top+2;
  417.             bounds.right  = thumb.right-1;
  418.             PaintRect(&bounds);  // Draw the hilite horiz part
  419.             
  420.             bounds.top    = thumb.top+2;
  421.             bounds.left   = thumb.left+1;
  422.             bounds.bottom = thumb.bottom-2;
  423.             bounds.right  = thumb.left+2;
  424.             PaintRect(&bounds);  // Draw the hilite vert part
  425.             
  426.             // Draw the text in the thumb
  427.             color.red = color.green = color.blue = 0x0000;
  428.             RGBForeColor(&color);
  429.             
  430.             TextFont(geneva);
  431.             TextSize(9);
  432.             
  433.             NumToPStr(value, (*inControl)->contrlValue);
  434.             
  435.             MoveTo(center.h - ((StringWidth(value)+1) >> 1), center.v + 3);
  436.             DrawString(value);
  437.         }
  438.         
  439.         // Copy it on screen
  440.         SetGWorld(oldGrafPort, oldGDevice);
  441.         
  442.         if (colorWindow)
  443.         {
  444.             backColor = ((CGrafPtr) (*inControl)->contrlOwner)->rgbBkColor;
  445.             foreColor = ((CGrafPtr) (*inControl)->contrlOwner)->rgbFgColor;
  446.             
  447.             color.red = color.green = color.blue = 0xFFFF;
  448.             RGBBackColor(&color);
  449.             
  450.             color.red = color.green = color.blue = 0x0000;
  451.             RGBForeColor(&color);
  452.         }
  453.         
  454.         CopyBits(
  455.                 (BitMap*) *offscreen->portPixMap,
  456.                 &(*inControl)->contrlOwner->portBits,
  457.                 &offscreen->portRect,
  458.                 &(*inControl)->contrlRect,
  459.                 srcCopy,
  460.                 nil);
  461.         
  462.         if (colorWindow)
  463.         {
  464.             RGBBackColor(&backColor);
  465.             RGBForeColor(&foreColor);
  466.         }
  467.         
  468.         // Clean up
  469.         UnlockPixels(offscreen->portPixMap);
  470.     }
  471. }
  472.  
  473.  
  474. /* =============================================================================
  475.  *        DoTestCntl (internal)
  476.  *
  477.  *    Returns the part code of the hit control, or zero if none.
  478.  * ========================================================================== */
  479. long DoTestCntl(
  480.     ControlHandle    inControl,
  481.     short            inVariation,
  482.     Point            inPoint)
  483. {
  484.     PrivateData**    privateData = (PrivateData**) (*inControl)->contrlData;
  485.     long            partCode;
  486.     short            position;
  487.     Rect            thumb;
  488.     
  489.     partCode = 0;
  490.     
  491.     if ((*inControl)->contrlVis && (*inControl)->contrlHilite != 255)
  492.     {
  493.         if (PtInRect(inPoint, &(*inControl)->contrlRect))
  494.         {
  495.             // Compute the thumb rect
  496.             position = ValToPos(inControl, inVariation);
  497.             
  498.             thumb = (*inControl)->contrlRect;
  499.             thumb.left  = position-kThumbLeft;
  500.             thumb.right = position+kThumbRight;
  501.             
  502.             // Check whether we're inside it
  503.             if (PtInRect(inPoint, &thumb))
  504.             {
  505.                 (*privateData)->offset = position-inPoint.h;
  506.             }
  507.             else
  508.             {
  509.                 (*privateData)->offset = 0;
  510.             }
  511.             
  512.             (*privateData)->origValue = (*inControl)->contrlValue;
  513.             
  514.             partCode = kControlIndicatorPart;
  515.         }
  516.     }
  517.     
  518.     return partCode;
  519. }
  520.  
  521.  
  522. /* =============================================================================
  523.  *        DoPosCntl (internal)
  524.  *
  525.  *    Called at mouse-up time with the movement delta.
  526.  * ========================================================================== */
  527. void DoPosCntl(
  528.     ControlHandle    inControl,
  529.     short            inVariation,
  530.     Point            inDelta)
  531. {
  532.     // Do nothing -- we've already done the deed
  533. }
  534.  
  535.  
  536. /* =============================================================================
  537.  *        DoThumbCntl (internal)
  538.  *
  539.  *    Fills out the slop, limit and axis fields of the drag record.
  540.  * ========================================================================== */
  541. void DoThumbCntl(
  542.     ControlHandle    inControl,
  543.     short            inVariation,
  544.     DragRecord*        inDragRecord)
  545. {
  546.     // Do nothing since we handle the drag ourselves
  547. }
  548.  
  549.  
  550. /* =============================================================================
  551.  *        DoDragCntl (internal)
  552.  *
  553.  *    Called repeatedly during drag to track mouse movement.
  554.  * ========================================================================== */
  555. void DoDragCntl(
  556.     ControlHandle    inControl,
  557.     short            inVariation)
  558. {
  559.     PrivateData**    privateData = (PrivateData**) (*inControl)->contrlData;
  560.     Point            mousePt;
  561.     short            value;
  562.     Rect            slop;
  563.     
  564.     slop = (*inControl)->contrlRect;
  565.     InsetRect(&slop, -100, -50);
  566.     
  567.     do
  568.     {
  569.         value = (*inControl)->contrlValue;
  570.         
  571.         GetMouse(&mousePt);
  572.         if (PtInRect(mousePt, &slop))
  573.         {
  574.             // Still inside -- track the pointer
  575.             PosToVal(inControl, inVariation, mousePt.h + (*privateData)->offset);
  576.         }
  577.         else
  578.         {
  579.             // Outside -- restore original value
  580.             (*inControl)->contrlValue = (*privateData)->origValue;
  581.         }
  582.         
  583.         // Draw if changed
  584.         if (value != (*inControl)->contrlValue)
  585.         {
  586.             DoDrawCntl(inControl, inVariation, 0);
  587.         }
  588.     }
  589.     while (StillDown());
  590. }
  591.  
  592.  
  593. /* =============================================================================
  594.  *        DoCalcCntlRgn (internal)
  595.  *
  596.  *    Fills in ioRegion with the control region.
  597.  * ========================================================================== */
  598. void DoCalcCntlRgn(
  599.     ControlHandle    inControl,
  600.     short            inVariation,
  601.     RgnHandle        ioRegion)
  602. {
  603.     RectRgn(ioRegion, &(*inControl)->contrlRect);
  604. }
  605.  
  606.  
  607. /* =============================================================================
  608.  *        DoCalcThumbRgn (internal)
  609.  *
  610.  *    Fills in ioRegion with the thumb region.
  611.  * ========================================================================== */
  612. void DoCalcThumbRgn(
  613.     ControlHandle    inControl,
  614.     short            inVariation,
  615.     RgnHandle        ioRegion)
  616. {
  617.     short            position;
  618.     Rect            thumb;
  619.     
  620.     position = ValToPos(inControl, inVariation);
  621.     
  622.     thumb = (*inControl)->contrlRect;
  623.     thumb.left  = position-kThumbLeft;
  624.     thumb.right = position+kThumbRight;
  625.     
  626.     RectRgn(ioRegion, &thumb);
  627. }
  628.  
  629.  
  630. /* =============================================================================
  631.  *        ValToPos (internal)
  632.  *
  633.  *    Converts the current control value into a position.
  634.  * ========================================================================== */
  635. static short ValToPos(
  636.     ControlHandle    inControl,
  637.     short            inVariation)
  638. {
  639.     short            denom;
  640.     short            position;
  641.     
  642.     denom = (*inControl)->contrlMax - (*inControl)->contrlMin;
  643.     
  644.     position = ((long)((*inControl)->contrlValue - (*inControl)->contrlMin) *
  645.             (((*inControl)->contrlRect.right - kThumbRight) -
  646.              ((*inControl)->contrlRect.left + kThumbLeft)) + ((denom+1)>>1)) / denom +
  647.             ((*inControl)->contrlRect.left + kThumbLeft);
  648.     
  649.     if (position < (*inControl)->contrlRect.left + kThumbLeft)
  650.     {
  651.         position = (*inControl)->contrlRect.left + kThumbLeft;
  652.     }
  653.     
  654.     if (position > (*inControl)->contrlRect.right - kThumbRight)
  655.     {
  656.         position = (*inControl)->contrlRect.right - kThumbRight;
  657.     }
  658.     
  659.     return position;
  660. }
  661.  
  662.  
  663. /* =============================================================================
  664.  *        PosToVal (internal)
  665.  *
  666.  *    Changes the control value to reflect the given position.
  667.  * ========================================================================== */
  668. static void PosToVal(
  669.     ControlHandle    inControl,
  670.     short            inVariation,
  671.     short            inPosition)
  672. {
  673.     short            denom;
  674.     
  675.     denom =    ((*inControl)->contrlRect.right - kThumbRight)-
  676.             ((*inControl)->contrlRect.left  + kThumbLeft);
  677.     
  678.     (*inControl)->contrlValue = ((long)(inPosition - ((*inControl)->contrlRect.left  + kThumbLeft)) *
  679.         ((*inControl)->contrlMax-(*inControl)->contrlMin) + ((denom+1)>>1)) / denom +
  680.         (*inControl)->contrlMin;
  681.     
  682.     if ((*inControl)->contrlValue < (*inControl)->contrlMin)
  683.     {
  684.         (*inControl)->contrlValue = (*inControl)->contrlMin;
  685.     }
  686.     
  687.     if ((*inControl)->contrlValue > (*inControl)->contrlMax)
  688.     {
  689.         (*inControl)->contrlValue = (*inControl)->contrlMax;
  690.     }
  691. }
  692.  
  693.  
  694. /* =============================================================================
  695.  *        NumToPStr (internal)
  696.  *
  697.  *    Converts the number to a string.  Using the toolbox incurred too much junk
  698.  *    in the link for me to feel good.
  699.  * ========================================================================== */
  700. void NumToPStr(
  701.     Str255            outStr,
  702.     long            inValue)
  703. {
  704.     unsigned char*    p;
  705.     long            val;
  706.     long            place;
  707.     long            digit;
  708.     Boolean            leading;
  709.     
  710.     p = &outStr[1];
  711.     
  712.     if (inValue == 0)
  713.     {
  714.         *p++ = 0;
  715.     }
  716.     else
  717.     {
  718.         // Strip the negative
  719.         val = inValue;
  720.         if (val < 0)
  721.         {
  722.             *p++ = '-';
  723.             val = -val;
  724.         }
  725.         
  726.         // Convert from MSD on down
  727.         place = 1000000000;
  728.         leading = true;
  729.         do
  730.         {
  731.             // Extract the digit
  732.             digit = val/place;
  733.             val -= digit*place;
  734.             
  735.             // Use it
  736.             if (digit != 0 || !leading)
  737.             {
  738.                 *p++ = '0'+digit;
  739.                 leading = false;
  740.             }
  741.             
  742.             // Prepare for the next digit
  743.             place /= 10;
  744.         }
  745.         while (place != 0);
  746.     }
  747.     
  748.     outStr[0] = p-outStr-1;
  749. }
  750.  
  751.  
  752.